package ArithmeticObjects;
import java.util.ArrayList;
import java.util.List;

import utils.ByteTree;

/**
 * Representing an array of field elements
 * @author Idan
 */
public class FieldElementArray extends ElementArray {

	private List<FieldElement> feArr;
	private Field Zq;
	
	/**
	 * creates a FieldElementArray from a given ByteTree representing it and a Field indicating its order
	 * @param bt a ByteTree representing the FieldElementArray
	 * @param Zq a Field indicating its order
	 * @throws Exception in case the construction of the array failed
	 */
	public FieldElementArray(ByteTree bt, Field Zq) throws Exception {
		this.Zq = Zq;
		feArr = new ArrayList<FieldElement>();
		for (int i=0; i<bt.getNumOfChildren(); i++)
			feArr.add(new FieldElement(bt.getChild(i), Zq));
	}
	
	/**
	 * creates a ModularGroupArray from an array of elements and a Group indicating its order
	 * @param elements Array of ModularGroupElements
	 * @param Gq Group indicating its order
	 * @throws Exception if the construction failed
	 */
	public FieldElementArray(Element[] elements, Field Zq) throws Exception {
		this.Zq = Zq;
		feArr = new ArrayList<FieldElement>();
		for (int i=0; i < elements.length; i++)
			feArr.add(new FieldElement(elements[i].getValue(), Zq));
	}
	
	@Override
	public Element getElementForIndex(int i)
	{
		return feArr.get(i);
	}
	
	@Override
	public void addElement(Element e) throws Exception
	{
		if (!(e instanceof FieldElement))
			throw new Exception("Wrong class, Expected: FieldElement, got: " + e.getClass().getName());
		feArr.add((FieldElement)e);
	}
	
	@Override
	public ElementArray arrayMultiply(ElementArray Ea) throws Exception {
		if (this.getArraySize()!=(Ea.getArraySize()))
			throw new Exception("Cannot multiply arrays of different sizes");
		
		Element[] arr=new Element[this.getArraySize()];
		for (int i=0; i<this.getArraySize(); i++)
			arr[i]=this.getElementForIndex(i).multiply(Ea.getElementForIndex(i));
		return new FieldElementArray(arr, Zq);
	}
	
	@Override
	public int getArraySize() {
		return feArr.size();
	}
	
	@Override
	public String toString() {
		String s = "";
		for (int i=0; i<feArr.size(); i++)
			s += feArr.get(i).toString()+"\n";
		return s;
	}
	
	/**
	 * @return the FieldElementArray's order
	 */
	public Element getOrder() {
		return Zq.getOrder();
	}

	@Override
	public ByteTree getByteTree() throws Exception {
		Element[] arr = new Element[this.getArraySize()];
		feArr.toArray(arr);
		return ByteTree.createArrayByteTree(arr,(Zq.getOrder().value.bitLength() + 7) / 8);
	}
}